package practica2bc.recuperacion;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.*;

import practica2bc.anotacion.Foto;


import practica2bc.recuperacion.Stemmer.*;

import es.ucm.fdi.gaia.ontobridge.OntoBridge;
import es.ucm.fdi.gaia.ontobridge.OntologyDocument;

public class RecuperacionTextual {
	private HashMap<String,ArrayList<Integer>> listaInvertida=new HashMap<String,ArrayList<Integer>>();
	private static RecuperacionTextual recuperacionTextual;
	private ArrayList<Foto> fotos;
	private ArrayList<String> listaParada;
	private OntoBridge ob;
	
	
	public RecuperacionTextual(){
		ob = new OntoBridge();
		ob.initWithPelletReasoner();
		
		//ob.initWithDIGReasoner("localhost", 8080);
		
		OntologyDocument mainOnto = new OntologyDocument("http://www.semanticweb.org/ontologies/2008/1/Ontology1202481514781.owl","file:test/perdidos_4.owl");
		
		ArrayList<OntologyDocument> subOntologies = new ArrayList<OntologyDocument>();
		
		ob.loadOntology(mainOnto, subOntologies, false);
		listaParada=cargaListaParada();
		fotos= listaFotos();
		listaInvertida=generaListaInvertida();
	}

	public static RecuperacionTextual getInstancia(){
		if (recuperacionTextual==null){
			recuperacionTextual=new RecuperacionTextual();
		}
		return recuperacionTextual;
	}
	
		
	public HashMap<String,ArrayList<Integer>> generaListaInvertida(){
		int nTerminos;
		HashMap<String,ArrayList<Integer>> listaInvertida=new HashMap<String,ArrayList<Integer>>();
		StringTokenizer terminosQuery;
		Stemmer stemmer = new Stemmer();
	    for (int i = 0; i < fotos.size(); i++){
	    	try{
	    		Foto f=fotos.get(i);
	    		String url=f.getUrlDescripcion();
	    		BufferedReader br = new BufferedReader(new FileReader(url));
	    		StreamTokenizer tokens=new StreamTokenizer(br);
	    		tokens.lowerCaseMode(true);
	    		tokens.whitespaceChars('\u0000', '\u002F');
	    		tokens.whitespaceChars('\u003A', '\u003F');
	    		while (tokens.nextToken()!=StreamTokenizer.TT_EOF){
	    			if (tokens.ttype==StreamTokenizer.TT_WORD || tokens.ttype==StreamTokenizer.TT_NUMBER){
	    				String palabra;
	    				if (tokens.ttype==StreamTokenizer.TT_WORD) palabra=tokens.sval;
	    				else palabra=""+tokens.nval;
	    				if (!listaParada.contains(palabra)){
	    					palabra=stemmer.raiz(palabra);
	    					if (listaInvertida.containsKey(palabra)){
	    						ArrayList<Integer> a=listaInvertida.get(palabra);
	    						a.set(i, a.get(i) + 1);
	    					}
	    					else {
	    						ArrayList <Integer> a=nuevoArray(fotos.size());
	    						a.set(i, 1);
	    						listaInvertida.put(palabra, a);
	    					}
	    				}
	    			}	
	    		}
	    	}	
	    	catch(Exception e){
	    		e.printStackTrace();
	    	}
	    }	
		return listaInvertida;
	}
	
	public ArrayList<Foto> listaFotos(){
		Iterator<String> fotosOnt = ob.listDeclaredInstances("fotos");
		ArrayList<Foto> fotos= new ArrayList<Foto>();
		while(fotosOnt.hasNext()){
			String foto=fotosOnt.next();
			Iterator<String> aux;
			aux = ob.listPropertyValue(foto, "urlfoto");
			String urlFoto=aux.next();
			aux = ob.listPropertyValue(foto, "urltexto");
			String urlTexto=aux.next();
			urlFoto=urlFoto.replace("^^http://www.w3.org/2001/XMLSchema#string", "");
			urlTexto=urlTexto.replace("^^http://www.w3.org/2001/XMLSchema#string", "");
			fotos.add(new Foto(urlFoto,urlTexto));
		}
		return fotos;
	}
	
	public ArrayList<String> cargaListaParada(){
		 String FICHERO_LISTA_PARADA = "./ListaParada/listaParada.txt";
         ArrayList<String> lista=new ArrayList<String>();
		 try {
		      BufferedReader br = new BufferedReader(new FileReader(FICHERO_LISTA_PARADA));
		      String s;
		      while ((s = br.readLine())!= null) {
		        s.trim();
		    	lista.add(s);
		      }
		      br.close();
      	    } 
	    catch (Exception e) {
		      System.out.println(e.toString());
	    }
	    return lista;
	}

	private ArrayList<Integer> nuevoArray(int tamano){
		ArrayList<Integer> a=new ArrayList<Integer>(tamano);
		for (int i=0; i < tamano; i++)
			a.add(0);
		return a;
	}
	
	public ArrayList<String> preprocesa(String query){
		ArrayList<String> consulta=new ArrayList<String>();
		Stemmer stemmer = new Stemmer();
		StringReader br = new StringReader(query); 
		StreamTokenizer tokens=new StreamTokenizer(br);
		tokens.lowerCaseMode(true);
		tokens.whitespaceChars('\u0000', '\u002F');
		tokens.whitespaceChars('\u003A', '\u003F');
		try{
			while (tokens.nextToken()!=StreamTokenizer.TT_EOF){
				if (tokens.ttype==StreamTokenizer.TT_WORD || tokens.ttype==StreamTokenizer.TT_NUMBER){
					String palabra;
					if (tokens.ttype==StreamTokenizer.TT_WORD) palabra=tokens.sval;
					else palabra=""+tokens.nval;
					if (!listaParada.contains(palabra)){
						palabra=stemmer.raiz(palabra);
						consulta.add(palabra);
					}
				}	
			}
		}catch (Exception e){
			e.printStackTrace();
		}
		return consulta;
	}
	
	public ArrayList<Foto> busquedaSintactica(String query){
		double similitud[] = new double[fotos.size()];
		ArrayList<String> consulta=preprocesa (query);
		ArrayList<Foto> urls = new ArrayList<Foto>();
		for (int i = 0; i < fotos.size(); i++){
			similitud[i] =0;
		}
		ArrayList<Integer> NDAs=new ArrayList<Integer>(fotos.size());
		for (int i = 0; i < fotos.size(); i++){
			double numerador=0;
			double denominador=0;
			for (int k = 0; k < consulta.size(); k++){
				String lexema=consulta.get(k);
				ArrayList<Integer> apariciones=listaInvertida.get(lexema);
				if (apariciones!=null){
					if (i==0) NDAs.add(calculaNDA(apariciones));
					double aux=apariciones.get(i)*(Math.log((double)fotos.size()/NDAs.get(k)) / Math.log(2));
					numerador+=aux;
					denominador+=aux*aux;
				}	
			}
			similitud[i]=numerador/Math.sqrt(denominador);
			if (similitud[i]>0.4){
				urls.add(fotos.get(i));
			}
		}
		
		return urls;
	}

	public int calculaNDA(ArrayList<Integer> a){
		int nda=0;
		for (int i=0; i < a.size(); i++){
			if (a.get(i) > 0) nda=nda+1;
		}
		return nda;
	}

	public OntoBridge getOb() {
		return ob;
	}

	public void setOb(OntoBridge ob) {
		this.ob = ob;
	}
}


